import axios from "axios";
import qs from "qs";
import { httpCode } from "./httpCode";
import { Router } from "@angular/router";
import { clearStore, getStore } from "@/utils";
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
let defaultConfig = {
  timeout: 8000
};
const prefixPath = "/api";

class Http {
  //私有属性
  static #instance;
  constructor(config) {
    if (!Http.instance) {
      Http.instance = this;
    } else {
      return Http.instance;
    }
    if (config) {
      defaultConfig = {
        ...defaultConfig,
        ...config
      };
    }
    this.myAxios = axios.create(defaultConfig);
    this.interceptorsRequest();
    this.interceptorsResponse();
  }

  //请求拦截
  interceptorsRequest() {
    this.myAxios.interceptors.request.use(
      config => {
        const token = getStore({ name: "userInfo" }).token || "";
        const headers = {
          ...(config.headers ? config.headers : {})
        };
        if (token) {
          headers["Authorization"] = `Bearer ${token}`;
        }

        config.headers = headers;
        config.cancelToken = source.token;
        return config;
      },
      error => {
        throw new Error(JSON.stringify(error));
      }
    );
  }
  interceptorsResponse() {
    const handleSuccess = res => {
      if (res.code == "401") {
        //处理token过期
        throw new Error("token过期");
        clearStore();
        this.router.navigate(["/login"]);
      } else {
        return res;
      }
    };
    // 响应拦截
    this.myAxios.interceptors.response.use(
      response => {
        const res = handleSuccess(response.data);
        return res;
      },
      error => {
        // 用户没有网络情况 或者 timeout时间过期
        if (!error.response && JSON.stringify(error).includes("timeout of")) {
          throw new Error("网络请求超时,请稍后再试。");
          return;
        }

        if (axios.isCancel(error) && !error.response) {
          return new Promise(() => {});
        }
        const { code, msg } = error.response.data;
        if (code >= 500) {
          throw new Error(msg);
        } else {
          // 返回体有数据返回的
          return handleSuccess(data);
        }
      }
    );
  }
  /**
   * @method 请求
   * @param { string } method 发送的方式
   * @param { stinng } url 请求的url
   * @param { object } config 配置项
   * @returns
   */
  request(method, url, config = {}) {
    if (!method || !url) {
      throw new Error(`请传入${method ? "url" : "method"}`);
      return;
    }
    /**
     * @param { any } data 发送的数据
     * @param { object } extraConfig 跟config传的参数一样，这个权重最大， 例如一个接口多个发送方式(method)，跟config传的参数一样，这个权重最大
     */
    return (data, extraConfig = {}) => {
      const params = {
        ...{
          method,
          url
        },
        ...config
      };

      // 处理业务层传进来额外的参数，例如一个接口多个发送方式(method)
      for (const key in extraConfig) {
        if (extraConfig.suffixUrl) {
          params.url += extraConfig.suffixUrl;
        } else {
          params[key] = extraConfig[key];
        }
      }

      if (method.toLowerCase() === "get" || method.toLowerCase() === "delete") {
        if (data && typeof data === "object") {
          params.params = data;
        } else if (typeof data === "string" || typeof data === "number") {
          params.url += data;
        }
      } else if (method.toLowerCase() === "post") {
        if (
          config.headers &&
          config.headers["content-type"].includes(
            "application/x-www-form-urlencoded"
          )
        ) {
          params.data = qs.stringify(data);
        } else {
          params.data = data;
        }
      } else {
        params.data = data;
      }
      return this.myAxios.request(params);
    };
  }
}

const http = new Http();
const request = http.request.bind(http);
export { request };
